﻿namespace Blaze.ConfigExportTool.Readers
{
    using System;
    using Aspose.Cells;
    using Exceptions;

    /// <summary>
    /// 用于读取<see cref="Worksheet"/>内的各种配置。
    /// </summary>
    public abstract class WorksheetReader
    {
        /// <summary>
        /// 获取或设置当前指针所在的行。
        /// </summary>
        protected int Row;

        /// <summary>
        /// 获取当前指针所在的单元格。
        /// </summary>
        public Cell Current
        {
            get { return mWorksheet.Cells[Row, Column]; }
        }

        /// <summary>
        /// 获取一个值，表示当前单元格是否为空。
        /// </summary>
        public bool IsEmpty
        {
            get { return string.IsNullOrEmpty(Current.DisplayStringValue); }
        }

        /// <summary>
        /// 获取或设置当前指针所在的列。
        /// </summary>
        protected int Column { get; set; }

        protected WorksheetReader(Cell beginCell)
        {
            mWorksheet = beginCell.Worksheet;
            Row = beginCell.Row;
            Column = beginCell.Column;
        }

        public T Read<T>(Func<T, WorksheetReader> handler) where T : class, new()
        {
            var ret = new T();
            return ret;
        }

        /// <summary>
        /// 从一个单元格中读取一个<see cref="bool"/>。
        /// </summary>
        /// <returns>当单元格的内容为“是”时将会返回真，否则返回假。</returns>
        public bool ReadBoolean(bool defaultValue = false)
        {
            var text = Current.DisplayStringValue.Trim();
            if (string.IsNullOrEmpty(text))
            {
                MoveNext();
                return defaultValue;
            }

            var ret = text == "是";
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从当前单元格中读取一个<see cref="float"/>。
        /// <param name="defaultValue">当单元格为空时，使用的默认值</param>
        /// </summary>
        public float ReadFloat(float defaultValue)
        {
            var ret = IsEmpty ? defaultValue : Current.FloatValue;
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从当前单元格中读取一个<see cref="float"/>。
        /// </summary>
        public float ReadFloat()
        {
            float ret;
            if (Current.Type == CellValueType.IsString)
            {
                if (!float.TryParse(Current.StringValue, out ret))
                    throw new CellException(Current, "错误的数字类型");
            }
            else
            {
                ret = Current.FloatValue;
            }
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从当前单元格中读取一个<see cref="int"/>。
        /// </summary>
        public int ReadInt32()
        {
            int ret;
            if (Current.Type == CellValueType.IsString)
            {
                if (!int.TryParse(Current.StringValue, out ret))
                    throw new CellException(Current, "错误的数字类型");
            }
            else
            {
                ret = Current.IntValue;
            }
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从当前单元格中读取一个<see cref="int"/>。
        /// <param name="defaultValue">当单元格为空时，使用的默认值</param>
        /// </summary>
        public int ReadInt32(int defaultValue)
        {
            var ret = IsEmpty ? defaultValue : Current.IntValue;
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从一个单元格中读取以半角逗号分隔的整型数组。
        /// </summary>
        public int[] ReadInt32Array()
        {
            var items = Current.DisplayStringValue.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            var ret = new int[items.Length];
            for (var i = 0; i < items.Length; i++)
                ret[i] = Int32.Parse(items[i]);
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从当前单元格中读取一个<see cref="int"/>，若单元格为空则返回null。
        /// </summary>
        public int? ReadNullableInt32()
        {
            var ret = IsEmpty ? null : (int?) Current.IntValue;
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从当前单元格中读取一个字符串，若单元格为空，则返回null。
        /// </summary>
        /// <returns></returns>
        public string ReadNullableString()
        {
            var ret = IsEmpty ? null : Current.DisplayStringValue;
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从多个单元格中读取字符串数组。
        /// </summary>
        /// <param name="count">字符串个数</param>
        public string[] ReadRangeStringArray(int count)
        {
            var ret = new string[count];
            for (var i = 0; i < count; i++)
                ret[i] = ReadString();
            return ret;
        }

        /// <summary>
        /// 从当前单元格中读取一个字符串。
        /// </summary>
        /// <returns></returns>
        public string ReadString()
        {
            var ret = Current.DisplayStringValue;
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 从一个单元格中读取以半角逗号分隔的字符串。
        /// </summary>
        /// <returns></returns>
        public string[] ReadStringArray()
        {
            var ret = Current.DisplayStringValue.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            MoveNext();
            return ret;
        }

        /// <summary>
        /// 忽略指定次数的读取指针（将指针顺延到指定次数之后的位置）。
        /// </summary>
        /// <param name="count">需要忽略的次数</param>
        public void Skip(int count = 1)
        {
            while (count-- > 0)
                MoveNext();
        }

        /// <summary>
        /// 当需要移动指针时调用此方法。
        /// </summary>
        protected abstract void MoveNext();

        private readonly Worksheet mWorksheet;
    }
}